/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package com.model.service;

import com.context.AppContext;
import com.context.properties.EnahoProperties;
import com.model.domain.proceso.envio.carga.OrigenCarga;
import com.model.domain.proceso.envio.subida.LogXmlTransferido;
import com.model.domain.proceso.envio.subida.LogXmlTransferidoError;
import com.model.domain.proceso.envio.subida.ModoEnvio;
import com.model.domain.proceso.envio.subida.xml.ArchivoXmlEnaho;
import com.model.domain.proceso.envio.subida.xml.TipoArchivoXmlEnaho;
import com.model.domain.ubicacion.ViviendaXmlTransferido;
import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import util.exception.ExceptionUtil;
import util.file.Archivo;
import util.file.xml.ArchivoXml;
import util.file.OperacionSubida;
import util.www.jdbc.JdbcUtil;
import util.log.MiLogger;
import util.www.sql.SelectSql;

/**
 * @author Rdelacruz
 */
public class LogXmlTransferidoService 
extends AbstractService
{   
    
    
    private LogXmlTransferidoErrorService logXmlTransferidoErrorService;
    private ViviendaXmlTransferidoService viviendaXmlTransferidoService;    
    private HogarXmlTransferidoService hogarXmlTransferidoService;
    private ConglomeradoService conglomeradoService;
    private ViviendaService viviendaService;
            
    
    public LogXmlTransferido findById(Connection con, Integer id) throws SQLException {
        Statement st = null;
        try {                        
            st = con.createStatement();
            //String sql = getSQLArchivosNoCargados("id_envio, rutaxmldata");            
            String sql = "select xml_data, rutaxmldata from Envios_logxmltransferidos"
                    + " where id_envio="+id;
            ResultSet rs = st.executeQuery(sql);   
            while(rs.next()) {
                LogXmlTransferido logxml = new LogXmlTransferido();
                logxml.setId(id);
                logxml.setDataXml(rs.getString(1));
                
                
                Archivo a = new Archivo();
                a.setUrl(rs.getString(2));
                
                OperacionSubida op = new OperacionSubida();
                op.setArchivo(a);
                
                logxml.setOperacionSubida(op);
                
                return logxml;
            }
        }
        finally {
            if(st!=null) st.close();
        }  
        
        return null;
    }
            
    /**
     * 
     * @param con
     * @param logger
     * @param tipo
     * @param usarDataBD true: se usa data xml de tabla Envios_logxmltransferidos; false:  se usa data XML de la ruta del archivo xml
     * @return
     * @throws SQLException 
     */
    public List<LogXmlTransferido> findLogXmlsExistentesSinProcesoDeCargaByTipo(Connection con, MiLogger logger, TipoArchivoXmlEnaho tipo, OrigenCarga origen, Integer nMaxArchivosACargar) throws SQLException {
        List<LogXmlTransferido> archivos = new ArrayList<LogXmlTransferido>();
        Statement st = null;
        try {                        
            st = con.createStatement();
                  
            String columna = origen==OrigenCarga.BASE_DATOS ? ",xml_data" : "";
            String where = nMaxArchivosACargar!=null ? "where nfila<="+nMaxArchivosACargar+"\n" : "";
            
            String sql = "select * from\n" +
"(select \n" +
"ROW_NUMBER() OVER(order by id_envio) as nfila,\n" +
"id_envio, rutaxmldata"+columna+"\n" +
"from Envios_logxmltransferidos\n" +
"where tipoxml='C' and existe=1 and procesoCarga=0 \n" +
") E\n" +
where +
"order by id_envio";
                     
            ResultSet rs = st.executeQuery(sql);   
            Archivo archivo = null;
            while(rs.next()) {
                try {
                    LogXmlTransferido logxml = new LogXmlTransferido();
                    logxml.setId(rs.getInt("id_envio"));

                    archivo = new Archivo();
                    archivo.setUrl(rs.getString("rutaxmldata"));

                    OperacionSubida op = new OperacionSubida();
                    op.setArchivo(archivo);
                    logxml.setOperacionSubida(op);

                    ArchivoXml archivoXml = null;
                    if(origen==OrigenCarga.BASE_DATOS) {
                        archivoXml = new ArchivoXml(rs.getString("xml_data"));
                    }
                    else if(origen==OrigenCarga.ARCHIVO) {
                        String urlXml = archivo.getUrl();
                        File fileXML = new File(urlXml);
                        archivoXml = new ArchivoXml(fileXML);
                    }
                    
                    ArchivoXmlEnaho archivoXmlEnaho = ArchivoXmlEnaho.parsear(archivoXml);
                    logxml.setArchivoXmlEnaho(archivoXmlEnaho);

                    archivos.add(logxml);
                    
                } catch(Exception ex) {
                    String arch = archivo !=null ? archivo.getUrl() : "";
                    logger.loge("No se pudo recuperar el archivo '"+arch+"'",ex);
                }
            }
        }
        finally {
            if(st!=null) st.close();
        }        
        return archivos;
    }
    
    private void updateFlag(Connection con, LogXmlTransferido logxml, String nombreFlag, int valorFlag) throws SQLException {        
        Integer id = logxml.getId();
        if(id==null)
            throw new SQLException("Id de LogXmlTransferido no puede ser nulo");
        
        Statement st = null;
        String sql = "UPDATE Envios_logxmltransferidos SET "+nombreFlag+"="+valorFlag+" WHERE id_envio="+id;
        
        try {
            st = con.createStatement();          
            //st.executeQuery(sql);//SQLServerException: La instrucción no devolvió un conjunto de resultados.
            st.executeUpdate(sql);
        }
        catch(SQLException e) {
            throw new SQLException("Error en '"+sql+"'",e);
        }
        finally {
            if(st!=null) st.close();
        }
    }
    
    public void updateFlagProcesoCarga(Connection con, LogXmlTransferido logxml, int valorFlag) throws SQLException {        
        updateFlag(con,logxml,"procesoCarga",valorFlag);
    }
    
    public void updateFlagExiste(Connection con, LogXmlTransferido logxml, int valorFlag) throws SQLException {        
        updateFlag(con,logxml,"existe",valorFlag);
    }
    
    
    /**
     * Crea instancias LogXmlTransferido y los coloca en la lista     * 
     * @param con
     * @param logger
     * @param lista Lista con los archivos subidos y no subidos
     * @throws Exception 
     */
    public void save(Connection con, MiLogger logger, List<LogXmlTransferido> lista) throws Exception {
        
        PreparedStatement ps_xml = null;//archivo XML
        LogXmlTransferido logxml = null;
        
        try {
            con.setAutoCommit(false);//COMMIT MANUAL
            
            String sql = "insert into Envios_logxmltransferidos"
                    + "(existe, procesoCarga, tipoxml, rutaxmldata, "
                    + "nombrexmldata, xml_data, IP, usuario, "
                    + "modoenvio, fechasubidaxml, tamanho) "
                    + "values (?,?,?,?,"
                    + "?,CAST(? AS XML),?,?,"
                    + "?,GETDATE(),?)";
            ps_xml = con.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
            //ps = con.prepareStatement(sql,new String[]{"id_envio"}); //Oracle                  
                      
            for(LogXmlTransferido log: lista) {                
                try {
                    logxml = log;
                    //logxml.setExiste(false);//el metodo anterior hace esto
                                        
                    OperacionSubida op = logxml.getOperacionSubida();
                            
                    if(!op.isOk())
                        throw new Exception(op.getMensajeError());
                    
                    Archivo a = op.getArchivo();

                    //if(!a.isExiste())//si no existe se lo ignora. No se lo registra
                    //    continue;

                    if(logxml.existeArchivoTransferido()) {//NOTA: solo registramos los archivos validos
                        ArchivoXmlEnaho arch;

                        
                        try {
                            String urlArchivo = a.getUrl();
                            //File archivoXml = new File(urlArchivo); 
                            //arch = ArchivoXmlEnaho.parsear(archivoXml);                 
                            //logxml.setArchivoXmlEnaho(arch);
                            arch = logxml.getArchivoXmlEnaho();
                            
                            //1. TABLA Envios_logxmltransferidos
                            switch(arch.getTipo()) {
                                case CAMPO:                                
                                case MARCO:                                

                                     //transferirDataXml_toBD_tablaLog(con,urlArchivo,origenDoc,usuario);                            
                                    ps_xml.setBoolean(1, true);//True, porque estamos registrando un archivo subido
                                    ps_xml.setInt(2, 0);//0: no cargado
                                    ps_xml.setString(3, arch.getTipo().getCodigo());
                                    ps_xml.setString(4, urlArchivo);  

                                    ps_xml.setString(5, a.getNombre());
                                    
                                    //FileUtil.escribirArchivo("d:/prueba.xml", arch.getArchivoXml().getDataXmlCompacta());
                                    ps_xml.setString(6, arch.getArchivoXml().getDataXmlCompacta());
                                    ps_xml.setString(7, logxml.getIp());                        
                                    ps_xml.setString(8, logxml.getUsuario());

                                    ps_xml.setString(9, ModoEnvio.WEB.name());
                                    //ps.setString(, FechaUtil.getFechaActualString());                        

                                    ps_xml.setLong(10, a.getTamanho());

                                    ps_xml.executeUpdate();                                                              

                                    int id_envio = JdbcUtil.getIdGeneradoInt(ps_xml);

                                    //Despues de registrar la subida:
                                    //a.getRegistroLog().setOk(true);

                                    logxml.setId(id_envio);                                                               

                                    updateFlagExisteDelRestoConMismoNombre(con, logxml, 0);
                            }
                        } catch(Exception ex) {
                            throw new Exception("No se pudo registrar el LOG del archivo "+a.getNombre(),ex);
                        }

                        
                        if(arch.getTipo()==TipoArchivoXmlEnaho.CAMPO) {
                            //2. TABLA Envios_hogarxmltransferidos
                            ViviendaXmlTransferido vxml = new ViviendaXmlTransferido();                            
                            vxml.setLogXmlTransferido(logxml);
                            viviendaXmlTransferidoService.save(con, vxml);
                        }
                        
                        
                        logxml.setSubido(true);
                    }
                    /*
                    else {
                        //3. TABLA Envios_logxmltransferidos_error
                        try {
                            LogXmlTransferidoError loge = new LogXmlTransferidoError();
                            loge.setLogXmlTransferido(logxml);
                            if(a!=null)
                                loge.setError(logxml.getOperacionSubida().getMensajeError());
                            logXmlTransferidoErrorService.save(con, loge);
                            logger.loge(loge.getError());
                        } catch(Exception ex) {
                            throw new Exception("No se pudo registrar el ERROR del archivo "+a.getNombre(),ex);
                        }
                    }
                    */

                    con.commit();
                    
                    
                } catch(Exception ex) {
                    if(con!=null) con.rollback();
                    
                    Exception e = new Exception("TRANSFERENCIA NO COMPLETADA",ex);
            
                    //En JSP
                    logger.loge(e);
                    
                    //En Archivo
                    //AppContext.getInstancia().getLoggerContext().getLoggerErrores().loge(e);
                    
                    //En la tabla de errores
                    LogXmlTransferidoError loge = new LogXmlTransferidoError();
                    loge.setLogXmlTransferido(logxml);
                    loge.setError(ExceptionUtil.getStackTrace(e));
                    logXmlTransferidoErrorService.save(con, loge);
                    if(con!=null) con.commit();//para guardar la linea anterior
                }
            }            
        }
        finally {                              
            if(ps_xml!=null) ps_xml.close();           
        }
    }
    
        /**
     * Marca como no existente el resto de archivos respecto a id_envio, porque se los esta reemplazando
     * @param con
     * @param nombre
     * @param id_envio 
     */
    private void updateFlagExisteDelRestoConMismoNombre(Connection con, LogXmlTransferido logxml, int valorFlag) throws SQLException {
        Statement st = null;
        PreparedStatement ps = null;
        try {      
            /////////////////
            st = con.createStatement();
            //String sql = getSQLArchivosNoCargados("id_envio, rutaxmldata");            
            String sql = "select id_envio from Envios_logxmltransferidos "
                    + "where id_envio <>"+logxml.getId()+" and nombrexmldata='"+logxml.getOperacionSubida().getArchivo().getNombre()+"'";
            ResultSet rs = st.executeQuery(sql); 
            /////////////////////////////
            
            sql = "update Envios_logxmltransferidos"
                    + " set existe="+valorFlag
                    + " where id_envio=? ;";
            
            ps = con.prepareStatement(sql);
            
            while(rs.next()) {
                int id = rs.getInt(1);
                ps.setInt(1, id);
                ps.executeUpdate();                
            }
        }
        finally {
            if(st!=null) st.close();
            if(ps!=null) ps.close();
        }
    }
    
    public void deleteArchivo(Connection con, LogXmlTransferido logxml) throws Exception {
        //ELIMINANDO ARCHIVO ORIGINAL
        Archivo archivo = logxml.getOperacionSubida().getArchivo();
        File file = new File(archivo.getUrl());
        
        if(file.exists()) {            
            file.delete();
            updateFlagExiste(con, logxml, 0);
        }
        
        //ELIMINANDO COPIA DEL ARCHIVO        
        EnahoProperties prop = AppContext.getInstancia().getEnahoProperties(con);
        File directorioCopia = new File(prop.getDirectorio_upload_copia());
        File fileCopia = new File(directorioCopia, file.getName());
        
        if(fileCopia.exists())
            fileCopia.delete();
    }
    
   
    public LogXmlTransferidoErrorService getLogXmlTransferidoErrorService() {
        return logXmlTransferidoErrorService;
    }

    public void setLogXmlTransferidoErrorService(LogXmlTransferidoErrorService logXmlTransferidoErrorService) {
        this.logXmlTransferidoErrorService = logXmlTransferidoErrorService;
    }

    public ViviendaXmlTransferidoService getViviendaXmlTransferidoService() {
        return viviendaXmlTransferidoService;
    }

    public void setViviendaXmlTransferidoService(ViviendaXmlTransferidoService viviendaXmlTransferidoService) {
        this.viviendaXmlTransferidoService = viviendaXmlTransferidoService;
    }

    public HogarXmlTransferidoService getHogarXmlTransferidoService() {
        return hogarXmlTransferidoService;
    }

    public void setHogarXmlTransferidoService(HogarXmlTransferidoService hogarXmlTransferidoService) {
        this.hogarXmlTransferidoService = hogarXmlTransferidoService;
    }

    public ConglomeradoService getConglomeradoService() {
        return conglomeradoService;
    }

    public void setConglomeradoService(ConglomeradoService conglomeradoService) {
        this.conglomeradoService = conglomeradoService;
    }

    public ViviendaService getViviendaService() {
        return viviendaService;
    }

    public void setViviendaService(ViviendaService viviendaService) {
        this.viviendaService = viviendaService;
    }

    
    
    
}
